/*
 * MeasuringUtils.java
 *
 * Created on October 29, 2007, 1:08 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package atag.compiler.powerassigner;

/**
 *
 * @author Animesh
 */
public class MeasuringUtils {

    
    /** Creates a new instance of MeasuringUtils */
    public MeasuringUtils() {
    }
    
    /**
     * @prints stats for this assignment
     * @param m Number of tasks
     * @param n Number of nodes
     * @param T T_ik = cost of setting task i on node k
     * @param R R_ijk = cost at k for sending one data unit from i to j
     * @param f f_i = frequency of task i
     * @param s s_ij = amount of data transferred on (i,j) edge in DE
     * @param e0 e0_k = initial energy at node k
     * @param X X[i][k] = 1 if task i is assigned to node k
     */
    public static void reportStats(int m, int n, double[][] T,
            double[][][] R, double[] f,
            double[][] s, double[] e0, int[][] x){
        
        System.out.println("Here are the stats:\n");
        double totalC = 0;
        double maxC=-1;
        int maxC_Node = -1;
        
        for(int k=0; k<n; k++){
            //compute cost at each node k in the network
            
            /*********** begin ck computation ***************/
            double ck = 0;
            for(int i = 0; i < m; i++){
                ck += f[i]*T[i][k]*x[i][k];
            }
            
            for(int i = 0; i< m; i++){
                for(int j = 0; j<m; j++){
                    if(s[i][j] != 0){
                        //if the edge (i,j) exists
                        for(int a = 0; a < n; a++){
                            for(int b = 0; b < n; b++){
                                
//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);
                                
                                double ckdelta = f[i]*s[i][j]*R[a][b][k]*x[i][a]*x[j][b];
                                ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                            }
                        }
                    }
                }
            }
            
            // ck = ck/e0[k];
            
            /*************ck computation done****************/
            
            System.out.println("C_"+k+" = "+ck);
            
            totalC = totalC + ck;
            
            if(ck > maxC){
                //if this node is the max cost
                maxC = ck;
                maxC_Node = k;
            }
        }
        
        System.out.println("Max Energy at Node "+maxC_Node+" : "+maxC);
        System.out.println("Total Energy : "+totalC);
        
    }
    
    /**
     * @prints stats for this assignment
     * @param m Number of tasks
     * @param n Number of nodes
     * @param T T_ik = cost of setting task i on node k
     * @param R R_ijk\rho = cost at k for sending one data unit from i to j 
     * via route rho
     * @param f f_i = frequency of task i
     * @param s s_ij = amount of data transferred on (i,j) edge in DE
     * @param e0 e0_k = initial energy at node k
     * @param X X[i][k] = 1 if task i is assigned to node k
     * @param phi phi[i][j] = path option taken for edge (i,j)
     */
    public static void reportMultiPathStats(int m, int n, double[][] T,
            double[][][][] MR, double[] f, double[][] s, double[] e0,
            int[][] x, int[][] phi) {

        System.out.println("Here are the stats:\n");
        double totalC = 0;
        double maxC = -1;
        int maxC_Node = -1;

        for (int k = 0; k < n; k++) {
            //compute cost at each node k in the network

            /*********** begin ck computation ***************/
            double ck = 0;
            for (int i = 0; i < m; i++) {
                ck += f[i] * T[i][k] * x[i][k];
            }

            for (int i = 0; i < m; i++) {
                for (int j = 0; j < m; j++) {
                    if (s[i][j] != 0) {
                        //if the edge (i,j) exists
                        for (int a = 0; a < n; a++) {
                            for (int b = 0; b < n; b++) {

//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);

                                double ckdelta = f[i] * s[i][j] *
                                        MR[a][b][k][phi[i][j]] * x[i][a] * x[j][b];
                                ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                            }
                        }
                    }
                }
            }

            // ck = ck/e0[k];

            /*************ck computation done****************/
            System.out.println("C_" + k + " = " + ck);

            totalC = totalC + ck;

            if (ck > maxC) {
                //if this node is the max cost
                maxC = ck;
                maxC_Node = k;
            }
        }

        System.out.println("Max Energy at Node " + maxC_Node + " : " + maxC);
        System.out.println("Total Energy : " + totalC);
    //    throw new UnsupportedOperationException("Not yet implemented");
    }

    
    
    public static double maxCost(int m, int n, double[][] T,
            double[][][] R, double[] f, double[][] s, double[] e0,
            int[][] x) {
        
        double maxC=-1;
        int maxC_Node = -1;
        
        for(int k=0; k<n; k++){
            //compute cost at each node k in the network
            
            /*********** begin ck computation ***************/
            double ck = 0;
            for(int i = 0; i < m; i++){
                ck += f[i]*T[i][k]*x[i][k];
            }
            
            for(int i = 0; i< m; i++){
                for(int j = 0; j<m; j++){
                    if(s[i][j] != 0){
                        //if the edge (i,j) exists
                        for(int a = 0; a < n; a++){
                            for(int b = 0; b < n; b++){
                                
//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);
                                
                                double ckdelta = f[i]*s[i][j]*R[a][b][k]*x[i][a]*x[j][b];
                                ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                            }
                        }
                    }
                }
            }
            
            // ck = ck/e0[k];
            
            /*************ck computation done****************/
            
//            System.out.println("C_"+k+" = "+ck);
            
            if(ck > maxC){
                //if this node is the max cost
                maxC = ck;
                maxC_Node = k;
            }
        }
        return maxC;
    }
    
    
    /**
     * @returns the maximum cost incurred by any node
     * @param assignedTo contains the node the task is assigned to. -1
     * means not assigned yet
     *
     */
    public static double maxCost(int m, int n, double[][] T,
            double[][][] R, double[] f, double[][] s, double[] e0,
            int[] assignedTo) {
        
        double maxC=-1;
        int maxC_Node = -1;
        
        for(int k=0; k<n; k++){
            //compute cost at each node k in the network
            
            /*********** begin ck computation ***************/
            double ck = 0;
            for(int i = 0; i < m; i++){
                // add cost if i is assigned to k
                if(assignedTo[i] == k)
                    ck += f[i]*T[i][k];
            }
            
            for(int i = 0; i< m; i++){
                for(int j = 0; j<m; j++){
                    if(s[i][j] != 0){
                        //if the edge (i,j) exists
                        int a = assignedTo[i];
                        if(a!= -1){
                            int b = assignedTo[j];
                            if(b!=-1){
                                
//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);
                                
                                double ckdelta = f[i]*s[i][j]*R[a][b][k];
                                ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                            }
                        }
                    }
                }
            }
            
            // ck = ck/e0[k];
            
            /*************ck computation done****************/
            
//            System.out.println("C_"+k+" = "+ck);
            
            if(ck > maxC){
                //if this node is the max cost
                maxC = ck;
                maxC_Node = k;
            }
        }
        return maxC;
    }

    /**
     * @returns the total cost incurred by the system
     * @param assignedTo contains the node the task is assigned to. -1
     * means not assigned yet
     *
     */
    public static double totalCost(int m, int n, double[][] T,
            double[][][] R, double[] f, double[][] s, double[] e0,
            int[] assignedTo) {
        
        double totalC=0;
        
        for(int k=0; k<n; k++){
            //compute cost at each node k in the network
            
            /*********** begin ck computation ***************/
            double ck = 0;
            for(int i = 0; i < m; i++){
                // add cost if i is assigned to k
                if(assignedTo[i] == k)
                    ck += f[i]*T[i][k];
            }
            
            for(int i = 0; i< m; i++){
                for(int j = 0; j<m; j++){
                    if(s[i][j] != 0){
                        //if the edge (i,j) exists
                        int a = assignedTo[i];
                        if(a!= -1){
                            int b = assignedTo[j];
                            if(b!=-1){
                                
//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);
                                
                                double ckdelta = f[i]*s[i][j]*R[a][b][k];
                                ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                            }
                        }
                    }
                }
            }
            
            // ck = ck/e0[k];
            
            /*************ck computation done****************/
            
//            System.out.println("C_"+k+" = "+ck);
            
            totalC = totalC + ck;
        }
        return totalC;
    }
    
    
    /**
     * @returns the maximum cost incurred by any node
     * @param assignedTo contains the node the task is assigned to. -1
     * means not assigned yet
     * @param pathChoice contans the choice of path. -1 means not assigned
     *
     */
    public static double maxMultiPathCost(int m, int n, int numPaths,
            double[][] T,
            double[][][][] MR, double[] f, double[][] s, double[] e0,
            int[] assignedTo, int[][] pathChoice) {
        
        double maxC=-1;
        int maxC_Node = -1;
        
        for(int k=0; k<n; k++){
            //compute cost at each node k in the network
            
            /*********** begin ck computation ***************/
            double ck = 0;
            for(int i = 0; i < m; i++){
                // add cost if i is assigned to k
                if(assignedTo[i] == k)
                    ck += f[i]*T[i][k];
            }
            
            for(int i = 0; i< m; i++){
                for(int j = 0; j<m; j++){
                    if(s[i][j] != 0){
                        //if the edge (i,j) exists
                        int a = assignedTo[i];
                        if(a!= -1){
                            int b = assignedTo[j];
                            if(b!=-1){
                                
//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);
                                //pathChoice[i][j] should be positive. OK to cause exception
                                if(pathChoice[i][j] != -1){
                                    //i and j may be assigned already, but edge i-j may yet be unassigned
                                    double ckdelta = f[i]*s[i][j]*MR[a][b][k][pathChoice[i][j]];
                                    ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                                }
                            }
                        }
                    }
                }
            }
            
            // ck = ck/e0[k];
            
            /*************ck computation done****************/
            
//            System.out.println("C_"+k+" = "+ck);
            
            if(ck > maxC){
                //if this node is the max cost
                maxC = ck;
                maxC_Node = k;
            }
        }
        return maxC;
    }

    /**
     * @returns the total cost incurred by the system
     * @param assignedTo contains the node the task is assigned to. -1
     * means not assigned yet
     *
     */
    public static double totalMultiPathCost(int m, int n, int numPahs, double[][] T,
            double[][][][] MR, double[] f, double[][] s, double[] e0,
            int[] assignedTo, int[][] pathChoice) {
        
        double totalC=0;
        
        for(int k=0; k<n; k++){
            //compute cost at each node k in the network
            
            /*********** begin ck computation ***************/
            double ck = 0;
            for(int i = 0; i < m; i++){
                // add cost if i is assigned to k
                if(assignedTo[i] == k)
                    ck += f[i]*T[i][k];
            }
            
            for (int i = 0; i < m; i++) {
                for (int j = 0; j < m; j++) {
                    if (s[i][j] != 0) {
                        //if the edge (i,j) exists
                        int a = assignedTo[i];
                        if (a != -1) {
                            int b = assignedTo[j];
                            if (b != -1) {
                                if (pathChoice[i][j] != -1) {

//                                System.out.println("i = "+i+"; j = "+j+
//                                        "; a = "+a+"; b = "+b+"; k = "+k);

                                    double ckdelta = f[i] * s[i][j] * MR[a][b][k][pathChoice[i][j]];
                                    ck += ckdelta;
//                                System.out.println("Ck increment = "+ckdelta);
                                }
                            }
                        }
                    }
                }
            }
            
            // ck = ck/e0[k];
            
            /*************ck computation done****************/
            
//            System.out.println("C_"+k+" = "+ck);
            
            totalC = totalC + ck;
        }
        return totalC;
    }    
}